home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UPFKEY__ / UP_FKEY.C
C/C++ Source or Header  |  1990-02-10  |  5KB  |  167 lines

  1. /*
  2.  * Here's the plan:
  3.  *        1. post a double-click in the title bar of the frontmost window
  4.  *        2. wait for the parent window to appear
  5.  *        3. select the second window
  6.  *        4. post a COMMAND-W
  7.  *
  8.  * The problem here is between step 2 and 3.  If we leave the FKEY to let
  9.  * the Finder bring forth the parent window after step 2, we aren't around
  10.  * to perform step 3.  Note that we can't get the Finder to do step 3 by
  11.  * posting a mouse down event in the second window because the second
  12.  * window may be completely covered by the first window.
  13.  *
  14.  * This leads to the modified plan:
  15.  *
  16.  *        1. post a double-click in the title bar of the frontmost window
  17.  *        2. post a COMMAND-SHIFT-NUMBER keyboard event, where NUMBER is
  18.  *            the number of this FKEY
  19.  *        3. Return to Finder
  20.  *        4. Finder makes parent window appear
  21.  *        5. COMMAND-SHIFT-NUMBER is processed, bringing us back to the FKEY
  22.  *        6. select the second window
  23.  *        7. post a COMMAND-W
  24.  *
  25.  * Now we have a different problem.  The FKEY is invoked twice.  Since it has
  26.  * no global variables that will stick around between the two invocations, how
  27.  * to we tell them apart?  We will let the user do it for us!  The first time
  28.  * around, we will wait for the user to release one of the COMMAND, SHIFT, or
  29.  * NUMBER keys before returning to the Finder.  This lets us tell which pass we
  30.  * are on: if the keys are down, it is the first pass; if they are up, it is
  31.  * the second pass.
  32.  *
  33.  * This leads to the final plan of attack:
  34.  *
  35.  *        1. Check the keyboard status to see which pass we are on
  36.  *        2. if first pass, then
  37.  *            2a. post a double-click in title bar of front window
  38.  *            2b. post keyboard events to reinvoke FKEY
  39.  *            2c. post COMMAND-W
  40.  *            2d. wait for user to release key
  41.  *            2e. return to Finder
  42.  *        3. else
  43.  *            3a. select second window
  44.  *            3b. return to Finder
  45.  */
  46.  
  47. void main( void );
  48. void begin( void );
  49.  
  50. /*
  51.  * When we are invoked for the first time, STILL_DOWN will be true.
  52.  * When the user releases one of the keys, STILL_DOWN will become false.
  53.  */
  54. #define    STILL_DOWN    (*(unsigned short *)0x184 != 0)
  55.  
  56. /*
  57.  * Begin is here to get the proper FKEY header.  Make sure you have
  58.  * the custom header option checked in Think C!
  59.  */
  60. void begin()
  61. {
  62.     asm
  63.     {        
  64.         bra.s    @1
  65.         dc.w    0
  66.         dc.b    'F','K','E','Y'
  67.     @OurID:
  68.         dc.w    6
  69.         dc.w    0
  70.     @1:    lea        begin, A4
  71.         pea        main                ; I have no idea why I didn't use jmp...
  72.         rts
  73.     }
  74. }
  75.  
  76. void main()
  77. {
  78.     long p;
  79.     long * pp;
  80.     GrafPtr savePort;
  81.  
  82.     if ( ! STILL_DOWN )
  83.     {
  84.         /*
  85.          * Second pass.  We need to get the window zapped.
  86.          */
  87.         WindowPeek front;
  88.  
  89.         front = (WindowPeek)FrontWindow();
  90.         if ( front == 0 )
  91.             return;
  92.         /*
  93.          * If the second window is "reasonable", we will select it and let
  94.          * the COMMAND-W zap it.  If it is not reasonable, then the user
  95.          * probably did something like try to move up from the root.
  96.          * In this case, we get rid of the COMMAND-W.
  97.          */
  98.         if ( front->nextWindow != 0 && front->nextWindow->visible )
  99.             SelectWindow( front->nextWindow );
  100.         else
  101.             FlushEvents( keyDownMask|keyUpMask, 0 );
  102.         return;
  103.     }
  104.     /*
  105.      * First pass.  First step is to find the title bar of the front window
  106.      */
  107.     pp = (long *)FrontWindow();
  108.     GetPort( &savePort );
  109.     SetPort( pp );            /* so LocalToGlobal will work like we want */
  110.     p = pp[4];                /* top left of window... */
  111.     LocalToGlobal( &p );    /* ...in global co-ords */
  112.     SetPort( savePort );
  113.     asm
  114.     {
  115.         ;
  116.         ; make PostEvent think that the mouse is in the title bar
  117.         ;
  118.         move.l    0x830,-(a7)    ; this is where _PostEvent gets the mouse
  119.                             ; ...location from.  We are going to
  120.                             ; ..."borrow" it.
  121.         move.l    p, d0        ; Co-ords of top left of window
  122.         add.w    #4, d0        ; We compute the co-ords of
  123.         swap    d0            ; ...a point 4 pixels over
  124.         sub.w    #4, d0        ; ...and 4 pixels up.  This
  125.         swap    d0            ; ...is where we will put our
  126.         move.l    d0, 0x830    ; ...imaginary mouse
  127.         ;
  128.         ; Now we can post the double-click!
  129.         ;
  130.         move.w    0x17a,-(a7)    ; These are where _PostEvent gets the state
  131.         move.w    0x184,-(a7)    ; ...of the keyboard.
  132.         move.w    #0,0x17a    ; We want _PostEvent to think that no keys
  133.         move.w    #0,0x184    ; ...are pressed.
  134.         move    #1, a0
  135.         _PostEvent            ; mouse down
  136.         move    #2, a0
  137.         _PostEvent            ; mouse up
  138.         move    #1, a0
  139.         _PostEvent            ; mouse down
  140.         move    #2, a0
  141.         _PostEvent            ; mouse up
  142.         move.w    (a7)+,0x184    ; we can stop lying to _PostEvent now
  143.         move.w    (a7)+,0x17a
  144.         move.l    (a7)+,0x830
  145.         ;
  146.         ; The shift and command keys should still be down from the original
  147.         ; invocation of this FKEY
  148.         ;
  149.         move.w    #3, a0                ; key down
  150.         move.w    0x184, d0
  151.         _PostEvent
  152.         move.w    #4, a0                ; key up
  153.         move.w    0x184, d0
  154.         _PostEvent
  155.         move.w    #3, a0                ; key down
  156.         move.l    #0, d0
  157.         move.w    #0x0d00|'W', d0
  158.         _PostEvent
  159.         move.w    #4, a0                ; key up
  160.         move.l    #0, d0
  161.         move.w    #0x0d00|'W', d0
  162.         _PostEvent
  163.     }
  164.     while ( STILL_DOWN )
  165.         ;
  166. }
  167.